package junit;

import com.mpobjects.bdparsii.eval.Expression;
import com.mpobjects.bdparsii.eval.Parser;
import com.mpobjects.bdparsii.eval.Scope;
import com.mpobjects.bdparsii.eval.Variable;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import lombok.SneakyThrows;
import org.junit.Test;

import java.math.BigDecimal;

/**
 * @author zgn
 * @Description: simJunit
 * @date 2022/1/13 0013
 */
public class 数学函数Junit {
    @Test
    public void egMax() {//e.g.
        //region 1.模拟数据
        System.out.println("--------------------Start--------------------");
        //endregion

        //region 2.数据处理
        System.out.println("--------------------Deal--------------------");
        //endregion

        //region 3.数据展示
        System.out.println("--------------------Done--------------------");
        //endregion
    }
    @Test
    @SneakyThrows
    public void bdparsii_0_egMin() {//e.g.
        String exp = "2 + (7-5) * 3.14159 * x + sin(0)+AAA";

        // compile
        Scope scope = new Scope();
        Expression parsiiExpr = Parser.parse(exp,scope);
        Variable x = scope.getVariable("x");
        x.setValue(new BigDecimal(1));//8.28318

        Variable AAA = scope.getVariable("sin");
        AAA.setValue(new BigDecimal(1));

        // evaluate
        //double result = parsiiExpr.evaluate();
        //OR
        BigDecimal result = parsiiExpr.evaluate();
        System.out.println(result);//-> 2.0
    }

    @SneakyThrows
    @Test
    public void bdparsii_1_egMin() {//e.g.
        //region 基础demo
        Scope scope = new Scope();
        Variable a = scope.getVariable("a");
        Expression expr = Parser.parse("3 + a ^ 4", scope);
        a.setValue(4);
        System.out.println(expr.evaluate());
        a.setValue(5);
        System.out.println(expr.evaluate());
        //endregion

        //region 1(0) 不能解析
        Expression expr1 = Parser.parse("sin(0)");
        System.out.println(expr1.evaluate());
        //endregion

        //region AAA 默认为0
        Expression expr2 = Parser.parse("AAA");
        System.out.println(expr2.evaluate());
        //endregion
    }
    //公式 300W 4.9%年利 30年
    //一年/一般	4.35%
    //一年至五年	4.75%
    //五年以上	4.90%
    double all=1000000,interest=0.049,year=10;
    @Test
    @SneakyThrows
    public void bdparsii_银行利率_等额本息_egMin() {//e.g.
        //region
        //[月利率](‰)=年利率(%)÷12
        //等额本息：(贷款本金*月利率*(1+月利率)^还款月数)/((1+月利率)^还款月数-1)
        System.out.println("等额本息");

        String exp = "(贷款本金*月利率*(1+月利率)^还款月数)/((1+月利率)^还款月数-1)";

        BigDecimal 贷款本金=new BigDecimal(all);
        BigDecimal 月利率=new BigDecimal(interest/12);
        BigDecimal 还款月数=new BigDecimal(year*12);

        Scope scope = new Scope();
        Expression parsiiExpr = Parser.parse(exp,scope);
        //endregion

        //region 参数
        Variable value_贷款本金 = scope.getVariable("贷款本金");
        value_贷款本金.setValue(贷款本金);//8.28318

        Variable value_月利率 = scope.getVariable("月利率");
        value_月利率.setValue(月利率);//8.28318

        Variable value_还款月数 = scope.getVariable("还款月数");
        value_还款月数.setValue(还款月数);//8.28318

        BigDecimal result = parsiiExpr.evaluate();
        BigDecimal 总还款 = result.multiply(还款月数);
        BigDecimal 利息 = 总还款.subtract(new BigDecimal(all));
        //endregion

        //region 输出结果
        System.out.println("总还款:"+总还款);//-> 2.0
        System.out.println("月还款:"+总还款.divide(还款月数));//-> 2.0
        System.out.println("利息:"+利息);//-> 2.0
        //endregion
    }

    @Test
    @SneakyThrows
    public void bdparsii_银行利率_等额本金_egMin() {//e.g.
        //region 公式 30W 3%年利 5年
        System.out.println("等额本金");
        //一年/一般	4.35%
        //一年至五年	4.75%
        //五年以上	4.90%

        //[月利率](‰)=年利率(%)÷12
        //等额本金：每月还款金额=(贷款本金/还款月数)+(本金-已归还本金累计额)×每月利率

        String exp = "(贷款本金/还款月数)+(贷款本金-已归还本金累计额)*月利率";

        BigDecimal 贷款本金=new BigDecimal(all);
        BigDecimal 月利率=new BigDecimal(interest/12);
        BigDecimal 还款月数=new BigDecimal(year*12);
        BigDecimal 已归还本金累计额=new BigDecimal(0);
        BigDecimal 总还款=new BigDecimal(0);
        BigDecimal result=null;

        Scope scope = new Scope();
        Expression parsiiExpr = Parser.parse(exp,scope);
        //endregion

        //region 参数
        Variable value_贷款本金 = scope.getVariable("贷款本金");
        value_贷款本金.setValue(贷款本金);//8.28318

        Variable value_月利率 = scope.getVariable("月利率");
        value_月利率.setValue(月利率);//8.28318

        Variable value_还款月数 = scope.getVariable("还款月数");
        value_还款月数.setValue(还款月数);//8.28318

        for (int i = 0; i < year*12; i++) {
            result = parsiiExpr.evaluate();
            已归还本金累计额=已归还本金累计额.add(result);
            总还款=总还款.add(result);
        }

        BigDecimal 利息 = 总还款.subtract(new BigDecimal(all));
        //endregion

        //region 输出结果
        System.out.println("总还款:"+总还款);//-> 2.0
        System.out.println("月还款:"+总还款.divide(还款月数));//-> 2.0
        System.out.println("利息:"+利息);//-> 2.0
        //endregion
    }

    @Test
    @SneakyThrows
    public void bdparsii_剑圣历练正式环境百分比_egMin() {//e.g.×
        //String exp = "base*(1+range%)";
        //String exp = "range";
        String exp = "base*(100+range)/100";

        // compile
        Scope scope = new Scope();
        Expression parsiiExpr = Parser.parse(exp,scope);
        Variable base = scope.getVariable("base");
        base.setValue(new BigDecimal(100));//8.28318

        Variable range = scope.getVariable("range");
        range.setValue(new BigDecimal(5));//8.28318

        // evaluate
        BigDecimal result = parsiiExpr.evaluate();
        System.out.println(result);//-> 2.0
    }


    @Test
    @SneakyThrows
    public void QLExpress_0_egMin() {//e.g.
        ExpressRunner runner = new ExpressRunner();
        DefaultContext<String, Object> context = new DefaultContext();
        context.put("base",100);
        context.put("range",5);
        //String express = "base*(1+range%)";
        //String express = "range%";
        String express = "base*(100+range)/100";
        Object r = runner.execute(express, context, null, true, false);
        System.out.println(r);
    }

    @Test
    public void egMin() {//e.g.
    }
}
